package cn.sgjk.train.business.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.sgjk.train.business.domain.*;
import cn.sgjk.train.business.enums.ConfirmOrderStatusEnum;
import cn.sgjk.train.business.enums.SeatColEnum;
import cn.sgjk.train.business.enums.SeatTypeEnum;
import cn.sgjk.train.business.feign.MemberFeign;
import cn.sgjk.train.business.mapper.ConfirmOrderMapper;
import cn.sgjk.train.business.mapper.DailyTrainSeatMapper;
import cn.sgjk.train.business.mapper.cust.DailyTrainTicketMapperCust;
import cn.sgjk.train.business.req.ConfirmOrderDoReq;
import cn.sgjk.train.business.req.ConfirmOrderQueryReq;
import cn.sgjk.train.business.req.ConfirmOrderSaveReq;
import cn.sgjk.train.business.req.ConfirmOrderTicketReq;
import cn.sgjk.train.business.resp.ConfirmOrderQueryResp;
import cn.sgjk.train.common.context.LoginMemberContext;
import cn.sgjk.train.common.exception.BusinessException;
import cn.sgjk.train.common.exception.BusinessExceptionEnum;
import cn.sgjk.train.common.req.MemberTicketReq;
import cn.sgjk.train.common.resp.CommonResp;
import cn.sgjk.train.common.resp.PageResp;
import cn.sgjk.train.common.util.SnowUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * 确认订单服务
 *
 * @author sgjk
 * @date 2023/12/19
 */
@Service
public class AfterConfirmOrderService {

    private static final Logger LOG = LoggerFactory.getLogger(AfterConfirmOrderService.class);

    @Autowired
    private DailyTrainSeatMapper dailyTrainSeatMapper;

    @Autowired
    private DailyTrainTicketMapperCust dailyTrainTicketMapperCust;

    @Autowired
    private MemberFeign memberFeign;


    @Autowired
    private ConfirmOrderMapper confirmOrderMapper;

    /**
     *    选中座位后的事务处理：
     *       座位表修改售卖情况sell；
     *      余票详情表修改余票；
     *      为会员增加购票记录
     *      更新确认订单为成功
     */

    /**
     *  事务范围尽量缩小
     */

    //@Transactional
    @GlobalTransactional
    public void AfterDoComfire(DailyTrainTicket dailyTrainTicket,
                               List<DailyTrainSeat> finalSeatList,List<ConfirmOrderTicketReq> tickets,
                               ConfirmOrder confirmOrder) {
        LOG.info("seata全局事务id:{}", RootContext.getXID());

        for (int j = 0, finalSeatListSize = finalSeatList.size(); j < finalSeatListSize; j++) {
            DailyTrainSeat dailyTrainSeat = finalSeatList.get(j);
            DailyTrainSeat seatForUpdate = new DailyTrainSeat();
            seatForUpdate.setId(dailyTrainSeat.getId());
            seatForUpdate.setSell(dailyTrainSeat.getSell());
            seatForUpdate.setUpdateTime(new Date());
            dailyTrainSeatMapper.updateByPrimaryKeySelective(seatForUpdate);

            /**
             *   计算这个站卖出去后，影响了哪些站的余票库存
             *       影响的库存： 本次选座之前没卖过票，和本次购买的区间有交集的区间
             *       假设10个站，本次买4~7站
             *       原售： 001000001
             *       购买： 000011100
             *       原售： 0010111001
             *       原售： XXX111111X
             *       例如： 111：广州~上海~南京
             *             01110：深圳 ~ 广上南 ~ 北京
             *            如果买广州到南京的票 影响：1) 01110 中前一位(0) 深圳~北京  后一位(0) 这个区间不能买这个座位的票
             *                                 2) 01110 深圳 ~ 广州 也不能买这个座位的票
             *                                 3) 01110 南京 ~ 北京 也不能买这个座位的票
             *
             *
             *    Integer startIndex = 4;
             *    Integer endIndex = 7;
             *    Integer minStartIndex = startIndex -  往前碰到的最后一个零;          // 最小区间的开始值 startIndex往前找到最后一个0，碰到 1不找，1为上一站出售的座位
             *    Integer minEndIndex = startIndex + 1;   //最小区间(最左端 min)受影响区间    01 上面例子的 买深圳 ~ 广州 受影响
             *    Integer maxStartIndex =  endIndex - 1;  // 最大区间(最右端 max)受影响的开始值   10 上面例子的 买南京 ~ 北京 受影响
             *    Integer maxEndIndex = endIndex + 往后碰到的最后一个零;  //最大受影响区间  01110 即是 深圳 ~ 北京
             *
             */

            Integer startIndex = dailyTrainTicket.getStartIndex();
            Integer endIndex = dailyTrainTicket.getEndIndex();
            Integer maxStartIndex = endIndex - 1;
            Integer minEndIndex = startIndex + 1;
            char[] chars = seatForUpdate.getSell().toCharArray();

            Integer minStartIndex = 0;

            for (int i = startIndex - 1; i >= 0; i--) {
                char aChar = chars[i];
                if (aChar == '1') {
                    minStartIndex = i + 1;
                    break;
                }
            }

            LOG.info("影响出发站区间:{}-{}", minStartIndex, minStartIndex);

            Integer maxEndIndex = seatForUpdate.getSell().length();
            for (int i = endIndex; i < seatForUpdate.getSell().length(); i++) {
                char aChar = chars[i];
                if (aChar == '1') {
                    maxEndIndex = i;
                    break;
                }
            }
            LOG.info("影响到达站区间:{}-{}", minEndIndex, maxEndIndex);

            dailyTrainTicketMapperCust.updateCountBySell(
                    dailyTrainSeat.getDate(),
                    dailyTrainSeat.getTrainCode(),
                    dailyTrainSeat.getSeatType(),
                    minStartIndex,
                    maxStartIndex,
                    minEndIndex,
                    maxEndIndex
            );


            //调用会员服务接口，为会员增加一张车票
            MemberTicketReq memberTicketReq = new MemberTicketReq();
            memberTicketReq.setId(SnowUtil.getSnowflakeNextId());
            memberTicketReq.setMemberId(confirmOrder.getMemberId());
            memberTicketReq.setPassengerId(tickets.get(j).getPassengerId());
            memberTicketReq.setPassengerName(tickets.get(j).getPassengerName());
            memberTicketReq.setTrainDate(dailyTrainTicket.getDate());
            memberTicketReq.setTrainCode(dailyTrainSeat.getTrainCode());
            memberTicketReq.setCarriageIndex(dailyTrainSeat.getCarriageIndex());
            memberTicketReq.setSeatRow(dailyTrainSeat.getRow());
            memberTicketReq.setSeatCol(dailyTrainSeat.getCol());
            memberTicketReq.setStartStation(dailyTrainTicket.getStart());
            memberTicketReq.setStartTime(dailyTrainTicket.getStartTime());
            memberTicketReq.setEndStation(dailyTrainTicket.getEnd());
            memberTicketReq.setEndTime(dailyTrainTicket.getEndTime());
            memberTicketReq.setSeatType(dailyTrainSeat.getSeatType());
            memberTicketReq.setCreateTime(dailyTrainTicket.getStartTime());
            memberTicketReq.setUpdateTime(dailyTrainTicket.getUpdateTime());
            CommonResp<Object> commonResp = memberFeign.save(memberTicketReq);
            LOG.info("调用member，返回：{}",commonResp);


            ConfirmOrder confirmOrderStatus = new ConfirmOrder();
            confirmOrderStatus.setId(confirmOrder.getId());
            confirmOrderStatus.setUpdateTime(new Date());
            confirmOrderStatus.setStatus(ConfirmOrderStatusEnum.SUCCESS.getCode());
            confirmOrderMapper.updateByPrimaryKeySelective(confirmOrderStatus);
            LOG.info("订单成功完成:{}",confirmOrderStatus);

        }

//        try {
//            Thread.sleep(20000);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }
//        int i = 10;
//        i = 1 / 0;

    }
}
